<template>
    <div :id="'container' + $attrs.resultId" class="container"></div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
// 引入antv-G6
import G6 from '@antv/g6';
import { getLetterWidth, getTextSize } from '@antv/g6/lib/util/graphic';
import { thousandsFormat } from '@/utils/tools';

// 弹出层
const tooltip = new G6.Tooltip({
    getContent(e) {
        var tooltipHtml = '';
        var model: any = e.item.getModel();
        // console.log(model, 'model');
        if (model.branchName) {
            tooltipHtml = model.branchName + `<br/>` + model.diffValueDescribe;
        } else {
            tooltipHtml = String(model['label']); // 显示必须为string类型
        }
        // else if (model.tooltipLabel) {
        //     tooltipHtml = String(model['tooltipLabel']);
        // }
        return tooltipHtml;
    },

    itemTypes: ['node'],
    offsetX: 1,
    offsetY: 0,
    fixToNode: true,
    offset: 10,
});
const getWidthByNum = (cfg, styles, isGap?) => {
    if (cfg.depth == 0) {
        styles.width = getLetterWidth(cfg.label, 6) * (cfg.label as any)?.length || styles.width;
    } else if (cfg.proportional) {
        if (isGap) {
            styles.width = cfg.gapWidth;
            return styles.width;
        }
        styles.width = getTextSize(cfg.label, 10)[0] || styles.width;
    } else {
        if (isGap) {
            styles.width = cfg.gapWidth;
        } else {
            styles.width = cfg.actualWidth;
        }
        return styles.width;
    }

    if (styles.width < 120) {
        styles.width = 120;
    }
    return styles.width;
};

// G6的配置项
G6.registerNode(
    'icon-node',
    {
        // draw是绘制后的附加操作-节点的配置项  图形分组，节点中图形对象的容器
        drawShape(cfg: any, group) {
            // 获取节点的配置
            let styles = this.getShapeStyle(cfg);

            // 解构赋值
            const { labelCfg = {} } = cfg;
            // console.log(cfg, getLetterWidth(cfg.label, 6), 'width++++++++');
            // 不同得层级根据值展示不一样依据分支值设定宽度---展示全部的分支值
            // console.log(styles.width, 'before');
            let aWidth = getWidthByNum(cfg, styles);
            styles.width = aWidth;

            // styles.width = aWidth > 120 ? aWidth : 120;
            // console.log(styles.width, 'after');
            const w = styles.width;
            const h = styles.height;
            // 向分组中添加新的图形 图形 配置 rect矩形 xy 代表左上角坐标 w h是宽高
            const keyShape = group.addShape('rect', {
                attrs: {
                    ...styles,
                    x: -w / 2,
                    y: -h / 2,
                },
            });
            return keyShape;
        },
        // 更新节点后的操作，一般同 afterDraw 配合使用
        update: undefined,
    },
    'rect'
);
G6.registerEdge('flow-line', {
    // 绘制后的附加操作
    draw(cfg, group) {
        // console.log(cfg, group, 'cfg');

        // 边两端与起始节点和结束节点的交点；
        const startPoint = cfg.startPoint;
        const endPoint = cfg.endPoint;
        // 边的配置
        const { style } = cfg;
        const shape = group.addShape('path', {
            attrs: {
                stroke: style.stroke, // 边框的样式
                endArrow: style.endArrow, // 结束箭头
                // 路径
                path: [
                    ['M', startPoint.x, startPoint.y],
                    ['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
                    ['L', endPoint.x, (startPoint.y + endPoint.y) / 2],
                    ['L', endPoint.x, endPoint.y],
                ],
            },
        });

        return shape;
    },
});
// 选中时候背景色填充
const defaultStateStyles = {
    selected: {
        fill: '#f39500',
        stroke: '#fff',
        'text-node': {
            fill: '#fff',
        },
    },
};

// 默认边的颜色 末尾箭头
const defaultEdgeStyle = {
    stroke: '#333', // 边颜色
    endArrow: {
        path: G6.Arrow.triangle(4, 6, 8),
        fill: '#333',
    },
};

// 默认布局
// compactBox 紧凑树布局
// 从根节点开始，同一深度的节点在同一层，并且布局时会将节点大小考虑进去。
const defaultLayout = {
    type: 'compactBox', // 布局类型树
    direction: 'TB', // TB 根节点在上，往下布局
    // preventOverlap: true,
    // nodeSize: [120, 40],
    getId: function getId(d) {
        return d.id;
    },
    getHeight: function getHeight() {
        // 节点高度的回调函数
        return 40;
    },
    getWidth: $event => {
        // console.log($event, 'event');
        // // 节点横向间距的回调函数  水平间隙

        return 16;
    },
    // getVGap: function getVGap() {
    //     // 节点纵向间距的回调函数--垂直间隙
    //     return 60;
    // },
    getHGap: $event => {
        // 节点横向间距的回调函数  水平间隙
        let width = getWidthByNum($event, { width: 120 }, true) * 0.4;
        width = width > 60 ? width : 60;
        return width;
        // return 60;
    },
};

@Component({ name: 'BranchFlowChart', components: {} })
export default class BranchFlowChart extends Vue {
    loading: boolean = false;
    tableData: any[] = [];
    @Prop() proportional; // 是否为比例型
    @Prop() treedata: any;
    @Prop() reponseData: any; //  未经处理的响应数据
    graph = null;
    originGraphUrl = null;
    container = null;
    @Watch('treedata', { deep: true })
    changeData() {
        // console.log(this.treedata, 'llllll');
        if (Object.keys(this.treedata)?.length) {
            this.resizeLoad(this.graph, this.container);
            // console.log(Object.keys(this.treedata), 'data');
            this.graph.data(this.treedata);

            // 根据提供的数据渲染视图。
            this.graph.render();
            setTimeout(() => {
                this.$nextTick(() => {
                    // console.log(this.graph, 'graph');
                    this.originGraphUrl = this.graph.toDataURL();
                    console.log(this.originGraphUrl);
                });
            }, 500);
        }
    }
    mounted() {
        this.container = document.getElementById('container' + this.$attrs.resultId);
        console.log(this.container, 'container');

        this.G6init();
        this.changeData();
    }

    // resize大小适配
    resizeLoad(graph, container) {
        console.log(graph, container, '=+++++');

        if (!graph || graph.get('destroyed')) return;
        if (!container || !container.scrollWidth || !container.scrollHeight) return;
        let width = 0;
        let data = this.reponseData.diffNumeratorList.concat(this.reponseData.diffDenominatorList);
        let actualWidth = 0;
        data.map((item: any) => (actualWidth += item.actualWidth + 20));
        console.log(actualWidth, 'actualWidth');

        if (container.clientWidth > actualWidth) {
            width = container.clientWidth;
        } else {
            width = actualWidth;
        }
        graph.changeSize(width, container.clientHeight);
        // 根据提供的数据渲染视图。
        graph.render();
        graph.fitView();
    }

    G6init() {
        if (typeof window !== 'undefined') {
            window.onresize = () => {
                console.log(container.clientWidth, container.clientHeight, '----------');
                this.resizeLoad(graph, container);
                // graph.fitCenter();
            };
        }
        console.log(this.$attrs.resultId, 'this.$attrs.resultId');

        // 获取容器
        const container = this.container;
        // 获取容器的宽高
        let length = this.reponseData.diffNumeratorList?.length + this.reponseData.diffDenominatorList?.length || 0;
        console.log(length, 'length');

        // const width = container.scrollWidth * (length / 15 > 1 ? length / 15 : 1);
        const width = container.scrollWidth;

        const height = container.scrollHeight || 500;

        // Graph 是 G6 图表的载体-实例化
        const graph = new G6.TreeGraph({
            container: 'container' + this.$attrs.resultId, // 图的 DOM 容器
            width,
            height,
            fitView: true,
            fitViewPadding: [5, 5],
            maxZoom: 1.5,
            minZoom: 0.8,
            linkCenter: true, // 指定边是否连入节点的中心
            plugins: [tooltip], // 插件  minimap
            // fitViewPort: true,
            modes: {
                // 交互模式
                // default 模式中包含点击选中节点行为和拖拽画布行为;
                default: [
                    'scroll-canvas',
                    'hover-node',
                    {
                        type: 'click-select',
                        multiple: false,
                        // 是否允许该 behavior 发生。若返回 false，被操作的 item 不会被选中，也不会触发 'nodeselectchange' 时机事件
                        shouldBegin: e => {
                            // 允许该 behavior 发生
                            // if (e.item._cfg.model.depth != 0) return true;
                            return true;
                        },
                    },
                ],
            },
            // 默认状态下节点的配置
            defaultNode: {
                type: 'icon-node',
                size: [120, 30],
                // 默认节点的颜色 边 圆角的配置
                style: {
                    fill: '#fff',
                    stroke: '#333', // 边框夜色
                    radius: 5,
                },
                labelCfg: {
                    style: {
                        fill: '#000',
                        fontSize: 10,
                    },
                    // width: 200,
                    // height: 30,
                },
                // width: 'auto',
            },
            // 默认状态下边的配置，
            defaultEdge: {
                type: 'flow-line',
                style: defaultEdgeStyle,
            },
            // 各个状态下节点的样式-，例如 hover、selected，3.1 版本新增。
            nodeStateStyles: defaultStateStyles,

            // 各个状态下边的样式-，例如 hover、selected，3.1 版本新增。
            edgeStateStyles: defaultStateStyles,
            // 布局配置项
            layout: defaultLayout,
        });

        // 当 click-select 选中的元素集合发生变化时将会触发下面时机事件，evt 中包含相关信息
        graph.on('nodeselectchange', e => {
            // 当前操作的 item
            console.log(e, 'nodeselectchange');
            if (e.target) {
                let self = e.target._cfg;
                let model = self.model;
                let notRequest = false;
                if ((this.proportional && model.depth == 1) || model.depth == 0) {
                    notRequest = true;
                }
                this.$emit('branch-change', { serialNo: model.serialNo, branchNo: model.branchNo, notRequest, id: model.id });
                graph.setItemState(e.target, 'selected', true);
            }
        });

        this.graph = graph;
    }
}
</script>
<style scoped>
.container {
    height: calc(100% - 30px);
    width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    position: relative;
}
</style>
